/*
 * Copyright (c) 2022 Huawei Device Co., Ltd.
 * Licensed under the Apache License,Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

import CommonLog from "./CommonLog"
import { Music } from "./model/Music"
import media from '@ohos.multimedia.media'
import fileIO from '@ohos.fileio'


export class PlayerManager {
    private playerEvent: IPlayerEvent
    // 当前播放的音乐
    private currentMusicIndex: number = 0

    // OH media对象
    private player: media.AudioPlayer

    // 进度条定时器
    private progressIntervalID: number = 0

    //当前播放时间
    private currentTimeMs: number = 0

    //总播放时间
    private totalTimeMs: number = 0

    // 是否在播放
    private isPlaying: boolean = false

    // 音乐列表
    private musicList: Music[] = [
        {
            name: "Dynamic",
            author: "网络歌手1",
            //      url: "file://system/etc/dynamic.wav",
            url: "system/etc/dynamic.wav",
            backgroundColor: [['#FEFFFF', 0.0], ['#C2E9E7', 1.0]]
        },
        {
            name: "Demo",
            //      url: "file://system/etc/demo.wav",
            author: "网络歌手2",
            url: "system/etc/demo.wav",
            backgroundColor: [['#EBEAF8', 0.0], ['#97A2F9', 1.0]]
        }]

    constructor(event?: IPlayerEvent) {
        if (event) {
            this.playerEvent = event
            this.player = media.createAudioPlayer()

            CommonLog.info("constructor")
            this.player.on('finish', () => {
                CommonLog.info("finish")
                this.playNextMusic()
            })

            this.player.on('error', (err) => {
                CommonLog.info('Play music error = ' + JSON.stringify(err))
            });
        }
    }

    getMusicList() {
        return this.musicList
    }

    getCurrentMusic() {
        return this.musicList[this.currentMusicIndex]
    }

    /**
     * 播放指定音乐
     * @param index 序号
     */
    playSpecifyMusic(seekTo, index: number) {
        this.currentMusicIndex = index
        this.playerEvent.playEvent(this.getCurrentMusic());
        this.play(seekTo)
    }

    /**
     * 播放下一首音乐
     */
    playNextMusic() {
        if (this.currentMusicIndex + 1 == this.musicList.length) {
            this.currentMusicIndex = 0
        } else {
            this.currentMusicIndex++
        }

        this.playSpecifyMusic(-1, this.currentMusicIndex)
    }

    /**
     * 播放前一首音乐
     */
    playPreviousMusic() {
        if (this.currentMusicIndex == 0) {
            this.currentMusicIndex = this.musicList.length - 1
        } else {
            this.currentMusicIndex--
        }

        this.playSpecifyMusic(-1, this.currentMusicIndex)
    }

    play(seekTo) {
        CommonLog.info("play")
        if (this.player.state == 'playing' && this.player.src == this.getCurrentMusic().url) {
            return
        }

        if (this.player.state == 'idle' || this.player.src != this.getCurrentMusic().url) {
            this.player.reset()
            this.player.on('dataLoad', () => {
                CommonLog.info('dataLoad duration=' + this.player.duration)
                this.totalTimeMs = this.player.duration
                if (seekTo > this.player.duration) {
                    seekTo = -1
                }
                this.player.on('play', () => {
                    if (seekTo > 0) {
                        this.player.seek(seekTo)
                    }
                })

                this.player.play()
                this.setProgressTimer()
                this.isPlaying = true
            })


            CommonLog.info('before open')
            let fdNumber = fileIO.openSync(this.getCurrentMusic().url);
            CommonLog.info('after open' + JSON.stringify(fdNumber))
            let fdPath = 'fd://'
            //      this.player.src = this.getCurrentMusic().url
            this.player.src = fdPath + '' + fdNumber
            CommonLog.info('Preload music url = ' + this.player.src)


        }
        else {
            if (seekTo > this.player.duration) {
                seekTo = -1
            }
            this.player.on('play', () => {
                if (seekTo > 0) {
                    this.player.seek(seekTo)
                }
            })

            this.player.play()
            //this.setProgressTimer()
            this.isPlaying = true
        }


        this.playerEvent.playEvent(this.getCurrentMusic());
    }

    /**
     * 获取音乐总时间
     */
    getTotalTimeMs() {
        return this.totalTimeMs
    }

    /**
     * 设置进度
     * @param ms 进度
     */
    seek(ms) {
        this.currentTimeMs = ms;

        if (this.isPlaying) {
            CommonLog.info('MusicPlayer[PlayerModel] player.seek ' + ms);
            this.player.seek(ms);
        } else {
            CommonLog.info('MusicPlayer[PlayerModel] stash seekTo=' + ms);
        }
    }

    /**
     * 取消定时器
     */
    cancelProgressTimer() {
        if (typeof (this.progressIntervalID) != 'undefined') {
            clearInterval(this.progressIntervalID);
            this.progressIntervalID = undefined;
        }
    }

    setProgressTimer() {
        this.cancelProgressTimer()

        this.progressIntervalID = setInterval(() => {
            let timeMs = this.player.currentTime;
            this.currentTimeMs = timeMs;
            if (typeof (timeMs) === 'undefined') {
                timeMs = 0;
            }

            this.playerEvent.progressEvent(timeMs, this.totalTimeMs)
        }, 500)
    }

    pause() {
        CommonLog.info("pause")

        this.player.pause();
        //this.cancelProgressTimer()
        this.isPlaying = false
        this.playerEvent.pauseEvent(this.getCurrentMusic());
    }

    getCurrentMusicIndex() {
        return this.currentMusicIndex
    }

    getCurrentTimeMs() {
        return this.currentTimeMs
    }
}

export interface IPlayerEvent {
    playEvent(music: Music): void

    pauseEvent(music: Music): void

    progressEvent(currentTimeMs: number, totalTimeMs: number): void
}